package br.com.duosoftware.orcamento.managedbeans;

import br.com.duosoftware.orcamento.daos.CategoriaOrcamentoDAO;
import br.com.duosoftware.orcamento.daos.ConfirmacaoDAO;
import br.com.duosoftware.orcamento.daos.DotacaoDAO;
import br.com.duosoftware.orcamento.daos.ElementoDeDespesaDAO;
import br.com.duosoftware.orcamento.daos.FonteDeRecursoDAO;
import br.com.duosoftware.orcamento.daos.OrcamentoDAO;
import br.com.duosoftware.orcamento.daos.PlanoDeContaDAO;
import br.com.duosoftware.orcamento.daos.TipoCreditoDAO;
import br.com.duosoftware.orcamento.daos.TipoDespesaDAO;
import br.com.duosoftware.orcamento.entidades.CategoriaOrcamento;
import br.com.duosoftware.orcamento.entidades.Confirmacao;
import br.com.duosoftware.orcamento.entidades.Dotacao;
import br.com.duosoftware.orcamento.entidades.ElementoDeDespesa;
import br.com.duosoftware.orcamento.entidades.FonteDeRecurso;
import br.com.duosoftware.orcamento.entidades.Orcamento;
import br.com.duosoftware.orcamento.entidades.PlanoDeConta;
import br.com.duosoftware.orcamento.entidades.TipoCredito;
import br.com.duosoftware.orcamento.entidades.TipoDespesa;
import br.com.duosoftware.orcamento.services.OrcamentoService;
import br.com.duosoftware.orcamento.utils.ManagedBeanUtil;
import br.com.duosoftware.orcamento.utils.Mensagens;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import org.hibernate.exception.ConstraintViolationException;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Renato
 *
 */
@ManagedBean
@ViewScoped
public class OrcamentoBean implements Serializable {

    private Orcamento orcamento;
    private List<Orcamento> orcamentos;
    private OrcamentoDAO orcamentoDAO;
    private OrcamentoService orcamentoService;

    //
    ///****Select Itens****
    //
    private List<SelectItem> dotacoes;
    private List<SelectItem> elementosDespesa;
    private List<SelectItem> patrimonios;
    private List<SelectItem> vpds;
    private List<SelectItem> categoriasOrcamento;
    private List<SelectItem> tiposDespesa;
    private List<SelectItem> primarias;
    private List<SelectItem> tiposCredito;
    private List<SelectItem> fontesDeRecurso;
    //
    private DotacaoBean dotacaoBean;

    public OrcamentoBean() {

        orcamentoService = new OrcamentoService();

        dotacaoBean = (DotacaoBean) ManagedBeanUtil.getContextInfo("#{dotacaoBean}");

        orcamentoDAO = new OrcamentoDAO();

    }

    public Orcamento getOrcamento() {
        return orcamento;
    }

    public void setOrcamento(Orcamento orcamento) {
        this.orcamento = orcamento;
    }

    public List<Orcamento> getOrcamentos() {
        return orcamentos;
    }

    public void setOrcamentos(List<Orcamento> orcamentos) {
        this.orcamentos = orcamentos;
    }

    public OrcamentoService getOrcamentoService() {
        return orcamentoService;
    }

    public void setOrcamentoService(OrcamentoService orcamentoService) {
        this.orcamentoService = orcamentoService;
    }

    /**
     *
     *
     */
    public void inicializarOrcamentos() {

        Dotacao dotacao = dotacaoBean.getDotacao();

        if (dotacao != null && dotacao.getId() != null) {

            orcamentos = orcamentoDAO.listarOrcamentos(dotacao);

        } else {

            orcamentos = null;

        }

    }

    /**
     * <b>Método que inicializa o Orcamento a ser cadastrado.</b><p>
     *
     * @return void
     *
     */
    public void adicionarInicio() {

        Dotacao dotacao = dotacaoBean.getDotacao();

        if (dotacao == null) {

            Mensagens.mensagemDeAlerta("Selecione um registro",
                    "Selecione uma dotação para incluir um orçamento");

        } else {

            orcamento = new Orcamento();
            orcamento.setFichaDespesa(orcamentoDAO.obterSequencia());
            orcamento.setDotacao(dotacao);

            RequestContext.getCurrentInstance().execute("dlgOrcamento.show()");

        }
    }

    /**
     * <b>Método que adiciona ou edita um Orcamento</b><p>
     *
     * Após o término o método fecha o dialog de cadastro.
     * <p>
     *
     * @return void
     *
     */
    public void adicionarEditarFim() {

        if (!orcamentoService.verificarTotalValorDespesa(orcamento)) {

            Mensagens.mensagemDeErro("Valor Despesa", "A soma dos valores são maiores que o Valor Previsto da Dotação");

        } else {

            //orcamento.setFichaDespesa(orcamentoDAO.obterSequencia());

            orcamentoDAO.salvarOuAtualizar(orcamento);
            orcamento = new Orcamento();
            orcamentos = null;

            inicializarOrcamentos();

            RequestContext requestContext = RequestContext.getCurrentInstance();
            requestContext.execute("dlgOrcamento.hide()");
            requestContext.update("formDotacoes:dtOrcamentos");
            
        }
    }

    /**
     * <b>Método para iniciar o processo de edição de um Orcamento.</b>
     * <p>
     *
     * Ele verifica se há um Orcamento selecionada para edição, se não houver é
     * emitida uma mensagem pedindo que o usuário selecione uma.<p>
     *
     * Caso haja um Orcamento selecionado o médoto abre o dialog para edição<p>
     *
     * @return void
     *
     */
    public void editarInicio() {

        if (orcamento == null) {

            Mensagens.mensagemDeAlerta("Selecione um registro", "Selecione um re"
                    + "gistro para Editar");

        } else {

            RequestContext.getCurrentInstance().execute("dlgOrcamento.show()");

        }

    }

    /**
     * <b>Método para iniciar o processo de exclusão de um Orcamento.</b>
     * <p>
     *
     * Ele verifica se há um Orcamento selecionado para exclusão, se não houver
     * é emitida uma mensagem pedindo que o usuário selecione uma.<p>
     *
     * Caso haja um Orcamento selecionado o médoto abre um p:dialog para
     * confirma ção da exclusão.<p>
     *
     * @return void
     *
     */
    public void excluirInicio() {

        if (orcamento == null) {
            Mensagens.mensagemDeAlerta("Selecione um registro",
                    "Selecione um registro para excluir");
        } else {
            RequestContext.getCurrentInstance()
                    .execute("dlgExcluirOrcamento.show()");
        }

    }

    /**
     * <b>Método para excluir um Orcamento.</b>
     * <p>
     *
     * Ele verifica se a Orcamento selecionado para exclusão está sendo
     * utilizado por alguma outra tabela do banco. Se estiver uma mensagem de
     * aviso é dada ao usuário<p>
     *
     * @return void
     *
     */
    public void excluirFim() {

        try {

            orcamentoDAO.excluir(orcamento);
            orcamento = new Orcamento();
            orcamentos = null;

            inicializarOrcamentos();

        } catch (ConstraintViolationException e) {
            Mensagens.mensagemDeAlerta("Registro Utilizado",
                    "Esse registro está sendo utilizado");
        }

        RequestContext.getCurrentInstance()
                .execute("dlgExcluirOrcamento.hide()");

    }

    /**
     * <b> Método para cancelar uma operação de cadastro ou edição.</b>
     * <p>
     *
     * O método instancia um novo objeto na variável Orcamento para limpar as
     * infomações.<p>
     *
     * @return void
     */
    public void cancelar() {

        orcamento = new Orcamento();

        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.execute("dlgOrcamento.hide()");
        requestContext.update("formOrcamentos:dtOrcamentos");

    }

    //get SelectItens
    //
    public List<SelectItem> getDotacoes() {
        dotacoes = new LinkedList<SelectItem>();
        for (Dotacao dotacao : new DotacaoDAO()
                .listarDotacoes()) {
            dotacoes.add(new SelectItem(dotacao, dotacao.toString()));
        }
        return dotacoes;
    }

    //
    public List<SelectItem> getElementosDespesa() {
        elementosDespesa = new LinkedList<SelectItem>();
        for (ElementoDeDespesa elementoDeDespesa : new ElementoDeDespesaDAO()
                .listarElementosDeDespesa()) {
            elementosDespesa.add(new SelectItem(elementoDeDespesa, elementoDeDespesa.toString()));
        }
        return elementosDespesa;
    }

    //
    public List<SelectItem> getPatrimonios() {
        if (patrimonios == null) {
            patrimonios = new LinkedList<SelectItem>();
            for (PlanoDeConta planoDeConta : new PlanoDeContaDAO()
                    .listarPlanosDeConta(4, 1)) {
                patrimonios.add(new SelectItem(planoDeConta, planoDeConta.toString()));
            }
        }
        return patrimonios;
    }

    //
    public List<SelectItem> getVpds() {
        if (vpds == null) {
            vpds = new LinkedList<SelectItem>();
            for (PlanoDeConta planoDeConta : new PlanoDeContaDAO()
                    .listarPlanosDeConta(4, 3)) {
                vpds.add(new SelectItem(planoDeConta, planoDeConta.toString()));
            }
        }
        return vpds;
    }

    //
    public List<SelectItem> getCategoriasOrcamento() {

        categoriasOrcamento = new LinkedList<SelectItem>();

        for (CategoriaOrcamento categoriaOrcamento : new CategoriaOrcamentoDAO()
                .listarCategoriasOrcamento()) {

            categoriasOrcamento.add(new SelectItem(categoriaOrcamento, categoriaOrcamento.toString()));

        }

        return categoriasOrcamento;

    }

    //
    public List<SelectItem> getTiposDespesa() {
        tiposDespesa = new LinkedList<SelectItem>();
        for (TipoDespesa tipoDespesa : new TipoDespesaDAO()
                .listarTiposDespesa()) {
            tiposDespesa.add(new SelectItem(tipoDespesa, tipoDespesa.toString()));
        }
        return tiposDespesa;
    }

    //
    public List<SelectItem> getPrimarias() {
        if (primarias == null) { //Nos casos em que os dados são FIXOS
            primarias = new LinkedList<SelectItem>();
            for (Confirmacao confirmacao : new ConfirmacaoDAO()
                    .listarConfirmacoes()) {
                primarias.add(new SelectItem(confirmacao, confirmacao.toString()));
            }
        }
        return primarias;
    }

    //
    public List<SelectItem> getTiposCredito() {
        tiposCredito = new LinkedList<SelectItem>();
        for (TipoCredito tipoCredito : new TipoCreditoDAO()
                .listarTiposCredito()) {
            tiposCredito.add(new SelectItem(tipoCredito, tipoCredito.toString()));
        }
        return tiposCredito;
    }

    //
    public List<SelectItem> getFontesDeRecurso() {
        fontesDeRecurso = new LinkedList<SelectItem>();
        for (FonteDeRecurso fonteDeRecurso : new FonteDeRecursoDAO()
                .listarFontesDeRecurso()) {
            fontesDeRecurso.add(new SelectItem(fonteDeRecurso, fonteDeRecurso.toString()));
        }
        return fontesDeRecurso;
    }

}
